%{
#include <dirent.h> 
#include <stdlib.h> 
#include <string.h>
#include <unistd.h>
#include <error.h>
#include <sys/stat.h>

extern "C" {
int yywrap(void);
int yylex(void);
}
class ParseAdmin{
public:
	ParseAdmin();

public:
	void Reset();
	int GetBraceNum();
	void BraceNumAdd();
	void BraceNumDel();
private:
	int brace_num;
};
#define MAX_PATH_LEN (256)
#define     ENTER_FUNC  "sdk_stack_push((char *)__FUNCTION__, __LINE__);\n"
#define     EXIT_FUNC   "sdk_stack_pop();\n"

static char *str_enter = "extern void sdk_stack_push(char *name, int line);\n";
static char *str_exit = "extern void sdk_stack_pop();\n";

ParseAdmin admin;
FILE *fp_out = NULL;
bool isFunc(char *str);
%}

space [ \t]
word [_a-zA-Z]
number [0-9]
variable {word}+[{word}|{number}|_]*
funcname {word}+[{word}|{number}|_]*
callfunc {variable}{space}*\(.*\){space}*;{space}*\n

%x IN_FUNC
%%
^{space}*(static{space}*)*{word}+{space}+{funcname}{space}*\(.*\){space}*\n{space}*\{ {
	BEGIN IN_FUNC;
	admin.BraceNumAdd();
	fprintf(fp_out, "%s", yytext);
	//printf("func 11111111111111111111111111111 %s\n", yytext);
}

^{space}*(static{space}*)*{word}+{space}+{funcname}{space}*\(.*\){space}*\{{space}*\n {
	BEGIN IN_FUNC;
	admin.BraceNumAdd();
	fprintf(fp_out, "%s", yytext);
	//printf("func 2222222222222222222222222 %s\n", yytext);
}

<IN_FUNC>^{space}*("return"|"int"|"short"|"long"|"char"|"void"|"unsigned").*\n {
	fprintf(fp_out, "%s", yytext);
	//printf("get func declare!!!!!!!!!!!!!!!!!! %s\n", yytext);
}
<IN_FUNC>^{space}+while[^\n\{]*\n {
	fprintf(fp_out, "%s", yytext);
	//printf("get while!!!!!!!!!!!!!!!!!!\n");
}

<IN_FUNC>^{space}+if[^\n\{]*\n {
	fprintf(fp_out, "%s", yytext);
	//printf("get if!!!!!!!!!!!!!!!!!!\n");
}

<IN_FUNC>\{ {
	admin.BraceNumAdd();
	fprintf(fp_out, "{");
}

<IN_FUNC>\} {
	admin.BraceNumDel();
	fprintf(fp_out, "}");
	if (admin.GetBraceNum() == 0) {
		BEGIN 0;
	}
}

<IN_FUNC>^{space}*{variable}{space}*={space}*{callfunc} {
	//这里判断下,函数是否真实成立,判断下()括号是否一致
	//printf("get func %s\n", yytext);
	if (isFunc(yytext)) {
		int num = admin.GetBraceNum();
		char sstr[256] = {0};
		int index = 0;
		while(num--) {
			index += sprintf(sstr+index, "\t");
		}
		fprintf(fp_out, "%s{\n", sstr);
		fprintf(fp_out, "%s\t%s", sstr, ENTER_FUNC);
		fprintf(fp_out, "%s\t%s", sstr, yytext);
		fprintf(fp_out, "%s\t%s", sstr, EXIT_FUNC);
		fprintf(fp_out, "%s}\n", sstr);
	} else {
		fprintf(fp_out, "%s", yytext);
	}
}

<IN_FUNC>^{space}*{callfunc} {
	//这里判断下,函数是否真实成立,判断下()括号是否一致
	if (isFunc(yytext)) {
		int num = admin.GetBraceNum();
		char sstr[256] = {0};
		int index = 0;
		while(num--) {
			index += sprintf(sstr+index, "\t");
		}
		fprintf(fp_out, "%s{\n", sstr);
		fprintf(fp_out, "%s\t%s", sstr, ENTER_FUNC);
		fprintf(fp_out, "%s\t%s", sstr, yytext);
		fprintf(fp_out, "%s\t%s", sstr, EXIT_FUNC);
		fprintf(fp_out, "%s}\n", sstr);
	} else {
		fprintf(fp_out, "%s", yytext);
	}
}

<IN_FUNC>.|\n {fprintf(fp_out, "%c", *yytext);}

.|\n {fprintf(fp_out, "%c", *yytext);}
%%
int yywrap(void)
{
	return 1;
}

extern FILE *yyin;

void scan_file(char *filename)
{
	char *filetmp = "tmp.c";
	FILE *fp_in = NULL;

	
	fp_in = fopen(filename, "r");
	fp_out = fopen(filetmp, "w");
	if (!fp_in || !fp_out) {
		printf("fopen failed %s \n%s\n", filename, filetmp);
		goto end;
	}

	fprintf(fp_out, "%s", str_enter);
	fprintf(fp_out, "%s", str_exit);

	yyin = fp_in;
	admin.Reset();
	do {
		yylex();
	}while(!feof(yyin));

end:
	if (fp_in) {
		fclose(fp_in);
	}
	if (fp_out) {
		fclose(fp_out);
	}
	rename(filetmp, filename);
}

void scanf_dir(char *path)
{
	DIR *d = NULL;
    struct dirent *dp = NULL; 
    struct stat st;   
    char p[MAX_PATH_LEN] = {0};
    int len;

    if(stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) {
        printf("invalid path: %s\n", path);
        return;
    }
    if(!(d = opendir(path))) {
        printf("opendir[%s] error: %m\n", path);
        return;
    }
    while((dp = readdir(d)) != NULL) {
        if((!strncmp(dp->d_name, ".", 1)) || (!strncmp(dp->d_name, "..", 2))) {
            continue;
        }
        snprintf(p, sizeof(p) - 1, "%s/%s", path, dp->d_name);
        stat(p, &st);
        if(!S_ISDIR(st.st_mode)) {
        	//过滤下c文件
			len = strlen(p);
			if (p[len-1] != 'c' || p[len-2] != '.') {
				continue;
			}
			//过滤下功能文件
			if (strncmp(dp->d_name, "sdk_misc_priv.c", strlen("sdk_misc_priv.c")) == 0 ||
				strncmp(dp->d_name, "cl_log.c", strlen("cl_log.c")) == 0) {
				continue;
			}
            printf("%s\n", dp->d_name);
            scan_file(p);
        } else {
            printf("******%s/\n", dp->d_name);
            scanf_dir(p);
        }
    }
    closedir(d);
}

int main(int argc, char **argv)
{
	char *dir = argv[1];
	
	scanf_dir(dir);
	
	return 0;
}

ParseAdmin::ParseAdmin()
{
	Reset();
}

void ParseAdmin::Reset()
{
	brace_num = 0;
}

int ParseAdmin::GetBraceNum()
{
	return brace_num;
}

void ParseAdmin::BraceNumAdd()
{
	brace_num++;
}

void ParseAdmin::BraceNumDel()
{
	brace_num--;
}

bool isFunc(char *str)
{
	int l_num = 0;
	int r_num = 0;
	int len;
	int i;

	len = strlen(str);

	//要求,最后一个有效字符是')',且'(',')'个数要相等
	for(i = 0; i < len; i++) {
		switch(str[i]) {
		case '(':
			l_num++;
			break;
		case ')':
			r_num++;
			break;
		default:
		break;
		}
	}

	return ((l_num != 0) && (l_num == r_num));
}